# checking python version
!python --version
Python 3.10.12
Python is a great general-purpose programming language on its own, but with the help of a few popular libraries (numpy, scipy, matplotlib) it becomes a powerful environment for scientific computing.
I expect that many of you will have some experience with Python; for the rest of you, this section will serve as a quick crash course both on the Python programming language and on the use of Python for scientific computing.
In this tutorial, we will cover:
As of Janurary 1, 2024, Python has officially dropped support for python2
. We’ll be using Python 3.10 for this iteration of the course. You can check your Python version at the command line by running python --version
.
Python is a high-level, dynamically typed multiparadigm programming language. Python code is often said to be almost like pseudocode, since it allows you to express very powerful ideas in very few lines of code while being very readable. As an example, here is an implementation of the classic quicksort algorithm in Python:
def quicksort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quicksort(left) + middle + quicksort(right)
quicksort([3,6,8,10,1,2,1])
[1, 1, 2, 3, 6, 8, 10]
Variables are stores of value
number
instead of x
Integers and floats work as you would expect from other languages:
# Quick number arithmetics
print(number + 1) # Addition
print(number - 1) # Subtraction
print(number * 2) # Multiplication
print(number ** 2) # Enumberponentiation
4
2
6
9
# Some compound assingment operators
number += 1 # number = number + 1
print(number)
number *= 2
print(number)
number /= 1 # number = number / 1
print(number)
number -= 2
print(number)
4
8
8.0
6.0
<class 'float'>
2.5 3.5 5.0 6.25
Python implements all of the usual operators for Boolean logic, but uses English words rather than symbols:
Now we let’s look at the operations:
A string is a sequence of characters under some quotes. Eg.
hello = 'hello' # String literals can use single quotes
world = "world" # or double quotes; it does not matter
print(hello, len(hello))
hello 5
I love to code in JavaScript
# formatting by indexing
statement = '{0} loves to code in {2} and {1}'
statement.format('Juma', 'Python', 'JavaScript')
'Juma loves to code in JavaScript and Python'
# formatting by name
statement = '{name} loves to code in {language1} and {language2}'
statement.format(language2='Python', name='Juma', language1='JavaScript')
'Juma loves to code in JavaScript and Python'
# String Literal Interpolation
name = 'Juma'
language1 = 'JavaScript'
language2 = 'Python'
statement = f'{name} loves to code in {language1} and {language2}'
print(statement)
Juma loves to code in JavaScript and Python
String objects have a bunch of useful methods; for example:
string_ = "hello"
print(string_.capitalize()) # Capitalize a string
print(string_.upper()) # Convert a string to uppercase; prints "HELLO"
print(string_.rjust(7)) # Right-justify a string, padding with spaces
print(string_.center(7)) # Center a string, padding with spaces
print(string_.replace('l', '(ell)')) # Replace all instances of one substring with another
print(' world '.strip()) # Strip leading and trailing whitespace
Hello
HELLO
hello
hello
he(ell)(ell)o
world
statement = 'i love to code in Python '
capitalized = statement.capitalize()
upped = statement.upper()
replaced = statement.replace('Python', 'javascript')
statement.strip()
'i love to code in Python'
You can find a list of all string methods in the documentation.
A list is an ordered collection of python objects or elements. A list can contain objects of different data types
list_of_numbers = [3, 1, 2] # Create a list
print(list_of_numbers)
print(list_of_numbers[2])
print(list_of_numbers[-1]) # Negative indices count from the end of the list; prints "2"
[3, 1, 2]
2
2
[3, 1, 'foo']
[3, 1, 'foo', 'bar']
last_item = list_of_numbers.pop() # Remove and return the last element of the list
print(last_item) # returns the last item
print(list_of_numbers) # Modifies the original list
bar
[3, 1, 'foo']
Research on: - del
- remove()
As usual, you can find all the gory details about lists in the documentation.
In addition to accessing list elements one at a time, Python provides concise syntax to access a range of values in a list; this is known as slicing:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(list_of_numbers) # Prints "[0, 1, 2, 3, 4]"
print(list_of_numbers[2:4]) # Get a slice from index 2 to 4 (exclusive); prints "[2, 3]"
print(list_of_numbers[2:]) # Get a slice from index 2 to the end; prints "[2, 3, 4]"
print(list_of_numbers[:2]) # Get a slice from the start to index 2 (exclusive); prints "[0, 1]"
print(list_of_numbers[:]) # Get a slice of the whole list; prints ["0, 1, 2, 3, 4]"
print(list_of_numbers[:-1]) # Slice indices can be negative; prints ["0, 1, 2, 3]"
list_of_numbers[2:4] = [8, 9] # Assign a new sublist to a slice
print(list_of_numbers) # Prints "[0, 1, 8, 9, 4]"
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 3]
[2, 3, 4, 5, 6, 7, 8, 9]
[0, 1]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
[0, 1, 8, 9, 4, 5, 6, 7, 8, 9]
A for loop
is used to loop through (or iterate) over a sequence of objects (iterable objects). Iterable objects in python include strings, lists, sets etc
You can loop over the elements of a list like this:
cat
dog
monkey
list_of_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
list_of_squared_numbers = []
for number in list_of_numbers:
list_of_squared_numbers.append(pow(number, 2))
list_of_squared_numbers
[1, 4, 9, 16, 25, 36, 49, 64, 81, 0]
If you want access to the index of each element within the body of a loop, use the built-in enumerate
function:
numbers = [0, 1, 2, 3, 4]
squares = []
for number in numbers:
squares.append(pow(number, 2))
print(squares)
[0, 1, 4, 9, 16]
You can make this code simpler using a list comprehension:
list_of_numbers = [0, 1, 2, 3, 4]
squares = [pow(number, 2) for number in list_of_numbers]
print(squares)
[0, 1, 4, 9, 16]
List comprehensions can also contain conditions:
numbers = [0, 1, 2, 3, 4]
even_squares = [pow(number, 2) for number in numbers if number % 2 == 0]
print(even_squares)
[0, 4, 16]
Research: - How to combine lists
# creating a dictionary
person = {
'first_name': 'Juma',
'last_name': 'Shafara',
'age': 51,
'married': True
}
person
{'first_name': 'Juma', 'last_name': 'Shafara', 'age': 51, 'married': True}
# accessing items in a dictionary
first_name = person['first_name']
last_name = person['last_name']
full_name = first_name + ' ' + last_name
# display
full_name
'Juma Shafara'
{'first_name': 'Juma',
'last_name': 'Shafara',
'age': 51,
'married': True,
'hobby': 'Coding'}
{'first_name': 'Juma',
'last_name': 'Shafara',
'age': 51,
'married': False,
'hobby': 'Coding'}
{'first_name': 'Juma',
'last_name': 'Shafara',
'married': False,
'hobby': 'Coding'}
Research: - How to remove an item using the del
method - How to iterate over objects in a dictionary - Imitate list comprehension with dictionaries
You can find all you need to know about dictionaries in the documentation.
animals = {'cat', 'dog'}
print('cat' in animals) # Check if an element is in a set; prints "True"
print('fish' not in animals) # prints "True"
True
True
animals.add('fish') # Add an element to a set
print('fish' in animals) # Returns "True"
print(len(animals)) # Number of elements in a set;
True
3
animals.add('cat') # Adding an element that is already in the set does nothing
print(len(animals))
animals.remove('cat') # Remove an element from a set
print(len(animals))
3
2
Research: - How to remove with discard()
- How to remove with pop()
- How to combine sets - How to get the difference between 2 sets - What happens when we have repeated elements in a set
Loops: Iterating over a set has the same syntax as iterating over a list; however since sets are unordered, you cannot make assumptions about the order in which you visit the elements of the set:
animals = {'cat', 'dog', 'fish'}
for index, animal in enumerate(animals):
print(f'{index}: {animal}')
0: fish
1: cat
2: dog
Set comprehensions: Like lists and dictionaries, we can easily construct sets using set comprehensions:
d = {(x, x + 1): x for x in range(10)} # Create a dictionary with tuple keys
t = (5, 6) # Create a tuple
print(type(t))
print(d[t])
print(d[(1, 2)])
<class 'tuple'>
5
1
Research: - Creating a tuple - Access items in a tuple - Negative indexing tuples - Using range of indexes - Getting the length of items in a tuple - Looping through a tuple - Checking if an item exists in a tuple - How to combine tuples - Prove that tuples are immutable
def
keyword. For example:def overWeightOrUnderweightOrNormal(weight_kg:float, height_m:float) -> str:
'''
Tells whether someone is overweight or underweight or normal
'''
height_m2 = pow(height_m, 2)
bmi = weight_kg / height_m2
rounded_bmi = round(bmi, 3)
if bmi > 24:
return 'Overweight'
elif bmi > 18:
return 'Normal'
else:
return 'Underweight'
overWeightOrUnderweightOrNormal(67, 1.7)
'Normal'
We will often use functions with optional keyword arguments, like this:
def greet(name:str='You')->str:
"""
This function greets people by name
Example1:
>>> greet(name='John Doe')
>>> 'Hello John Doe'
Example2:
>>> greet()
>>> 'Hello You'
"""
return f'Hello {name}'
# greet('Eva')
?greet
Signature: greet(name: str = 'You') -> str Docstring: This function greets people by name Example1: >>> greet(name='John Doe') >>> 'Hello John Doe' Example2: >>> greet() >>> 'Hello You' File: /tmp/ipykernel_66386/2049930273.py Type: function
# Instantiating a class
object1 = Person()
print(object1.first_name)
print(object1.last_name)
print(object1.age)
print(f'object1 type: {type(object1)}')
John
Tong
20
object1 type: <class '__main__.Person'>
# Instantiating a class
object2 = Person()
print(object2.first_name)
print(object2.last_name)
print(object2.age)
John
Tong
20
object1 = Person('Juma', 'Shafara', 24)
print(object1.first_name)
print(object1.last_name)
print(object1.age)
print(type(object1))
Juma
Shafara
24
<class '__main__.Person'>
object2 = Person('Eva', 'Ssozi', 24)
print(object2.first_name)
print(object2.last_name)
print(object2.age)
print(object2.greet('Shafara'))
print(type(object2))
Eva
Ssozi
24
Hello Shafara
<class '__main__.Person'>
Research: - Inheritance: This allows to create classes that inherit the attributes and methods of another class